package gobase

import (
	"fmt"
	"math"
	"strconv"
	"time"
)

func MakeVars(arg ...interface{}) interface{} {
	return arg
}

/*
*

	如果arg 是切片[]interface 则获取第一个元素
*/
func GetFirstFromVars(arg interface{}) interface{} {
	if arg == nil {
		return nil
	}
	if lst, ok := arg.([]interface{}); ok {
		if len(lst) == 0 {
			return nil
		}
		return lst[0]
	} else {
		return arg
	}
}

/*
*

	如果arg 是切片[]interface 则获取第idx元素
	idx 从0开始
*/
func GetIdxValFromVars(arg interface{}, idx int) interface{} {
	if arg == nil {
		return nil
	}
	if lst, ok := arg.([]interface{}); ok {
		if len(lst) < idx+1 {
			return nil
		}
		return lst[idx]
	} else {
		return nil
	}
}

func GetIdxValFromVarsDef(arg interface{}, idx int, def interface{}) interface{} {
	if arg == nil {
		return def
	}
	if lst, ok := arg.([]interface{}); ok {
		if len(lst) < idx+1 {
			return def
		}
		return lst[idx]
	} else {
		return def
	}
}

func GetIdxStrValFromVarsDef(arg interface{}, idx int, def string) string {
	val := GetIdxValFromVarsDef(arg, idx, def)
	return GetStrValue(val, def)
}

func GetIdxIntValFromVars(arg interface{}, idx int, def int) int {
	val := GetIdxValFromVarsDef(arg, idx, def)
	return int(GetInt64Value(val, int64(def)))
}

func GetIdxFloat64ValFromVars(arg interface{}, idx int, def float64) float64 {
	val := GetIdxValFromVarsDef(arg, idx, def)
	return GetFloat64Value(val, def)
}

func GetBoolValue(val interface{}, def bool) bool {
	switch vv := val.(type) {
	case []byte:
		if len(vv) == 1 {
			if vv[0] == 0 {
				return false
			} else {
				return true
			}
		}
		return TryStrToBool(string(vv), def)
	case string:
		return TryStrToBool(vv, def)
	default:
		if def {
			return GetInt32Value(vv, 1) == 1
		} else {
			return GetInt32Value(vv, 0) == 1
		}
	}
}

func GetInt32Value(val interface{}, def int32) int32 {
	switch vv := val.(type) {
	case string:
		v, err := strconv.ParseFloat(vv, 64)
		if err != nil {
			return def
		} else {
			return int32(math.Round(v))
		}
	case int:
		return int32(vv)
	case uint:
		return int32(vv)
	case int64:
		return int32(vv)
	case uint64:
		return int32(vv)
	case int8:
		return int32(vv)
	case uint8:
		return int32(vv)
	case int16:
		return int32(vv)
	case uint16:
		return int32(vv)
	case bool:
		if vv {
			return 1
		}
		return 0
	case int32:
		return vv
	case float64:
		return int32(math.Round(vv))
	case float32:
		return int32(math.Round(float64(vv)))
	case time.Time:
		return int32(vv.Unix())
	default:
		return int32(StrToIntDef(fmt.Sprintf("%v", val), 0))
	}
}

func GetInt64Value(val interface{}, def int64) int64 {
	switch vv := val.(type) {
	case string:
		v, err := strconv.ParseFloat(vv, 64)
		if err != nil {
			return def
		} else {
			return int64(math.Round(v))
		}
	case int:
		return int64(vv)
	case uint:
		return int64(vv)
	case int64:
		return int64(vv)
	case uint64:
		return int64(vv)
	case int8:
		return int64(vv)
	case uint8:
		return int64(vv)
	case int16:
		return int64(vv)
	case uint16:
		return int64(vv)
	case bool:
		if vv {
			return 1
		}
		return 0
	case uint32:
		return int64(vv)
	case int32:
		return int64(vv)
	case time.Time:
		return vv.UnixNano()
	case float64:
		return int64(math.Round(vv))
	case float32:
		return int64(math.Round(float64(vv)))
	default:
		return int64(StrToIntDef(fmt.Sprintf("%v", val), 0))
	}
}

func GetFloat64Value(val interface{}, def float64) float64 {
	switch vv := val.(type) {
	case string:
		v, err := strconv.ParseFloat(vv, 64)
		if err != nil {
			return def
		} else {
			return v
		}
	case int:
		return float64(vv)
	case int64:
		return float64(vv)
	case int8:
		return float64(vv)
	case int16:
		return float64(vv)
	case int32:
		return float64(vv)
	case float64:
		return vv
	case float32:
		return float64(vv)
	default:
		return def
	}
}

func GetStrValue(val interface{}, def string) string {
	switch vv := val.(type) {
	case []byte:
		return string(vv)
	case string:
		return vv
	case int:
		return fmt.Sprintf("%d", vv)
	case int64:
		return fmt.Sprintf("%d", vv)
	case int8:
		return fmt.Sprintf("%d", vv)
	case int16:
		return fmt.Sprintf("%d", vv)
	case int32:
		return fmt.Sprintf("%d", vv)
	case float64:
		return fmt.Sprintf("%f", vv)
	case float32:
		return fmt.Sprintf("%f", vv)
	case time.Time:
		return DateTimeString2(vv)
	default:
		return def
	}
}

func GetDateTimeValue(val interface{}, def time.Time) time.Time {
	switch vv := val.(type) {
	case []byte:
		return TryStrToTime(string(vv), def.Location(), def)
	case string:
		return TryStrToTime(vv, def.Location(), def)
	case int:
		return time.Unix(int64(vv), 0)
	case int64:
		return time.Unix(vv, 0)
	case int8:
		return time.Unix(int64(vv), 0)
	case int16:
		return time.Unix(int64(vv), 0)
	case int32:
		return time.Unix(int64(vv), 0)
	case float64:
		return time.Unix(int64(vv), 0)
	case float32:
		return time.Unix(int64(vv), 0)
	case time.Time:
		return vv
	default:
		return def
	}

}
